#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <cstdlib>
#include <stdlib.h>
#include "physicalDisk/PhysicalDisk.h"
#include "physicalDisk/DiskUtils.h"
#include "systemCallLayer/SystemCallLayer.h"
#include "libraryFunctions/LibraryFunctions.h"

#include "Shell.h"

using namespace std;

bool FileExists(string strFilename) {
  struct stat stFileInfo;
  bool blnReturn;
  int intStat;

  // Attempt to get the file attributes
  intStat = stat(strFilename.c_str(),&stFileInfo);
  if(intStat == 0) {
    blnReturn = true;
  } else {
    blnReturn = false;
  }

  return blnReturn;
}

int parseString(string sStringToParse, string delimChar, vector<string>& rReturnStringArray) {

 const char* str = sStringToParse.c_str();
 const char* seps = delimChar.c_str();
 char* token = NULL;
 int i = 0;

   /* Establish string and get the first token: */
   token =  strtok( (char*)str, seps );

   while( token != NULL ) {

      /* While there are tokens in "string" */

     rReturnStringArray.push_back( string(token));

     i++;

      /* Get next token: */
      token = strtok( NULL, seps );
   }

 return i;
}



void getAttrFromConfFile(char* fileName, vector<int>& params) {
	fstream confFile;
	string line;
	string delimChar = "[]";
	confFile.open(fileName, ios::in);
	if (confFile.is_open()) {

		//retrieves the block size
		getline(confFile,line);
		vector<string> dataBlockSize;
		parseString(line,delimChar,dataBlockSize);
		params.push_back(atoi(dataBlockSize[1].c_str()));

		//retrieves the number of inodes
		getline(confFile,line);
		vector<string> numOfInodes;
		parseString(line,delimChar,numOfInodes);
		params.push_back(atoi(numOfInodes[1].c_str()));

		//retrieves the number of inodes
		getline(confFile,line);
		vector<string> diskSize;
		parseString(line,delimChar,diskSize);
		params.push_back(atoi(diskSize[1].c_str()));

		confFile.close();

	}
}


int main(int argc, char* argv[]) {
	LibraryFunctions* libraryFunctions;
	if (FileExists("FILE_SYS")) {
		libraryFunctions = new LibraryFunctions();
		Shell* shell = new Shell (libraryFunctions);
		shell->run();

	} else {
		vector<int> params;
		getAttrFromConfFile(argv[1],params);
		/*for (int i=0; i<params.size(); i++) {
			cout << params[i] << endl;
		}*/
		libraryFunctions = new LibraryFunctions(params.at(2), params.at(0), params.at(1));
		Shell* shell = new Shell (libraryFunctions);
		shell->run();
	}

	//libraryFunctions->test();
	//libraryFunctions->run();



	//int* ans;
	//PhysicalDisk fd(4096,64,50);
	//PhysicalDisk fd(20480,64,50);
	//fd.main();

	/*FileSystem fs(4096,64,10);
	fs.main();*/


	//SystemCallLayer scl(4096,64,10,1);
	//scl.test();

	/*FreeAddressesBlock b(64,64,fd.getFileDesc());
	b.loadFromDisk();
	b.printAddresses();*/
	//cout << b << endl;
	//fd.readFromDisk(ans,4,4);

	//cout << *ans << endl;

	//int test = DiskUtils::getInt(ans,0);

	//cout << test << endl;
	//printf("address: %s",ans);

	/*///////////////////////////////////////////////////////////*/

	/*char newData[] = "abc";
	DiskServices ds(4096,64,10);
	int inode = ds.allocateInode();
	int block = ds.allocateDataBlock();
	cout << block << endl;
	ds.setDataBlock(inode,10,block);
	ds.freeDataBlock(block);
	ds.setDataBlock(inode,11,block);
	cout << ds.getDataBlock(inode,11) << endl;
	ds.writeBlock(block,newData);
	char* check;
	ds.readBlock(block, check);
	cout << check << endl;
	ds.setInodeType(inode,"hard-link");
	cout << ds.getInodeType(inode) << endl;
	ds.setFileSize(inode, 100);
	cout << ds.getFileSize(inode) << endl;*/

	/*///////////////////////////////////////////////////////////*/

	//LibraryFunctions libFunc;
	//libFunc.run();

	return 0;
}




